package com.gmrz.uas.plugin.cert;

import cfca.bankunion.common.vo.request.CertServiceRequestVO;
import cfca.bankunion.common.vo.response.CertServiceResponseVO;
import cfca.bankunion.toolkit.BankUnionClient;
import cfca.bankunion.toolkit.exception.TKException;
import com.gmrz.uas.plugin.authservice.AuthServiceConfigSpec;
import com.gmrz.uas.plugin.caservice.BaseCertServicePlugin;
import com.gmrz.uas.plugin.caservice.bean.CertBean;
import com.gmrz.uas.plugin.caservice.bean.CertTransactionTextBean;
import com.gmrz.uas.plugin.caservice.bean.P10Bean;
import com.gmrz.uas.plugin.caservice.bean.P7Bean;
import com.gmrz.uas.plugin.exception.PluginException;
import com.gmrz.uas.plugin.sm2.SM2Utils;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.koalii.svs.client.Svs2ClientHelper;
import com.union.api.UnionUAC;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.x500.X500Name;
import java.io.ByteArrayInputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import static com.gmrz.uas.plugin.cert.Convert.fromBase64;
import static com.gmrz.uas.plugin.cert.Convert.toBase64String;

/**
 * Created by gongyuqiang on 2017/5/25.
 */
public class DefaultCertService extends BaseCertServicePlugin {

    private static final Logger LOG = LogManager.getLogger(DefaultCertService.class);
    // RA 注册配置信息相关
    private static final String RA_NAME = "ra.name";// RA名称
    private static final String RA_URL = "ra.url";// 服务器地址
    private static final String RA_REG = "ra.reg";// 注册接口名称
    private static final String RA_DOWNLOAD = "ra.download";// 证书下载
    private static final String RA_KEYALG = "ra.keyAlg";// RSA算法名称
    private static final String RA_KEYLENGTH = "ra.keyLength";// RSA算法长度
    private static final String SM2_KEYALG = "sm2.keyAlg"; // SM2算法名称
    private static final String SM2_KEYLENGTH = "sm2.keyLength"; //SM2算法长度
    private static final String RA_TIMEOUT = "ra.timeout";// 连接超时时间
    private static final String RA_READ_TIMEOUT = "ra.readTime";// 读取超时时间
    private static final String RA_CERTYTPE = "ra.certType";// 证书类型
    private static final String RA_CUSTYPE = "ra.custType";// 客户类型
    //private static final String RA_BRANCH_CODE = "ra.branchCode";// 机构号
    //private static final String RA_CERT_DURATION = "ra.certDuration";
    // RA 注销配置信息相关
    private static final String RA_DEREG = "ra.dereg";// 注销接口名称
    // SVS 配置信息相关
    private static final String CONFIG_KEY_SVS_PROPFP = "svs.propfp";//验签服务器配置文件路径

    // 通信证书配置
    private static final String CONTENT_CERT_CONFIG = "content.certConfig";
    private static final String CONTENT_CERT_PASSWORD = "content.certPassword";

    // 信任证书链配置
    private static final String TRUST_STORE_PATH = "trust.storePath";
    private static final String TRUST_STORE_PASSWORD = "trust.storePassword";

    private static final String point = ".";

    // 负责人编号,当给人员申请证书时，该值无效，否则为必填项
    private static final String RA_PRINC_CODE = "ra.princCode";

    // 证书类型
    private static final String RA_PARENT_TYPE = "ra.parentType";

    // 证书所属机构号码
    private static final String RA_PARENT_CODE = "ra.parentCode";

    // 签名验签服务相关信息
    private static final String SVS_URL = "svs.url";
    private static final String SVS_PORT = "svs.port";
    private static final String SVS_TIMEOUT = "svs.timeout";

    private static String charSet = "utf-8";
    private static UnionUAC Signapi = null;

    public DefaultCertService() {
        this.allConfig = new HashMap<String, String>();
        this.allConfigSpec = new HashMap<String, AuthServiceConfigSpec>();

    }

    /**
     * 注册完成 申请证书
     */
    @Override
    public CertBean createCert(P10Bean p10Bean) throws PluginException {

        if (null == p10Bean || p10Bean.getP10().length <= 0) {
            throw new PluginException("Reg p10 data is null");
        }
        String custType = null,raBranchCode = null,duration = null;

        String appId = p10Bean.getAppID();

        //从ext字段获取客户类型、机构号。如果不上送，就从管理新系统里面取。
//        try{
//            String extJson = p10Bean.getExt();
//            JsonObject extObject = new JsonParser().parse(new String(Convert.fromBase64(extJson))).getAsJsonObject();
//            custType = extObject.get("custType").toString();
//            raBranchCode = extObject.get("branchCode").toString();
//        }catch (Exception e){
//            throw new PluginException("Failed to validate dn json exceptin: " + e.getMessage());
//        }k

        // 注册接口名称
        String rareg = getConfigFromFidoAdmin(RA_REG+point + appId, "Please add ra.reg on the fido admin");
        // 证书下载接口
        //String raDownload = getConfigFromFidoAdmin(RA_DOWNLOAD + point + appId,"Please add ra.download on the Fido admin");
        // RA名称
        String raname = getConfigFromFidoAdmin(RA_NAME + point + appId, "Please add ra.name on the fido admin");

        String raKeyAlg = null,raKeyLength = null;

        // 算法类型判断
        if(p10Bean.getAlgorithm() == 7){
            raKeyAlg = getConfigFromFidoAdmin(SM2_KEYALG + point + appId,"Please add sm2.keyAlg on the Fido Admin");
            raKeyLength = getConfigFromFidoAdmin(SM2_KEYLENGTH + point + appId,"Please add sm2.keyLength on the Fido Admin");
        }else{
            raKeyAlg = getConfigFromFidoAdmin(RA_KEYALG + point + appId,"Please add ra.keyAlg on the Fido Admin");
            raKeyLength = getConfigFromFidoAdmin(RA_KEYLENGTH + point + appId,"Please add ra.keyLength on the Fido Admin");
        }
        // 算法名称
        //String raKeyAlg = getConfigFromFidoAdmin(RA_KEYALG+point+appId, "Please add ra.keyAlg on the fido admin");
        // 算法长度
        //String raKeyLength = getConfigFromFidoAdmin(RA_KEYLENGTH+point+appId, "Please add ra.keyLength on the fido admin");
        // 证书类型
        String raCertType = getConfigFromFidoAdmin(RA_CERTYTPE+point+appId, "Please add ra.certType on the fido admin");
        // 客户类型
        custType = getConfigFromUser(custType, RA_CUSTYPE+point+appId, "Please add ra.custType on the fido admin");
        // 机构号
        //raBranchCode = getConfigFromUser(raBranchCode, RA_BRANCH_CODE+point+appId, "Please add ra.branchCode on the fido admin");
        // 证书有效期
        //duration = getConfigFromUser(duration, RA_CERT_DURATION+point+appId, "Please add ra.duration on the fido admin");
        // 负责人编号,当给人员申请证书时，该值无效，否则为必填项
        String raPrincCode = getConfigFromFidoAdmin(RA_PRINC_CODE + point + appId,"Please add ra.raPrincCode on the Fido Admin");
        // 证书类型
        String raParentType = getConfigFromFidoAdmin(RA_PARENT_TYPE + point + appId,"Please add re.ParentType on the Fido Admin");
        // 证书所属机构编号
        String raParentCode = getConfigFromFidoAdmin(RA_PARENT_CODE + point + appId,"Please add raParentCode on the Fido Admin");
        // 获取DN数据
        String userName, identType, identNo, dnIndexStr, p10Base64;

        try {
            String dnJson = p10Bean.getDnJson();
            LOG.debug("dnJson:"+dnJson);
            JsonObject jsonObject = new JsonParser().parse(new String(Convert.fromBase64(dnJson))).getAsJsonObject();
            identNo = jsonObject.get("cardNO").getAsString();
            identType = jsonObject.get("cardType").getAsString();
            userName = jsonObject.get("cardName").getAsString();
            LOG.info("########dn user name is:"+userName);
            // 获取P10数据
            p10Base64 = Convert.toBase64String(p10Bean.getP10());
        } catch (Exception e) {
            throw new PluginException("Failed to validate json exceptin: " + e.getMessage());
        }
        // 加载CFCA Client
        BankUnionClient client = getRaClint(appId);
        LOG.info("client info is :");
        if (null == client) {
            throw new PluginException("Failed to load ra client of createCert method");
        }
        CertServiceResponseVO certServiceResponseVO;

        // 申请证书
        try {
            // 拼接RA请求参数
            CertServiceRequestVO certServiceRequestVO = new CertServiceRequestVO();
            certServiceRequestVO.setTxCode(rareg); // 接口URL
            certServiceRequestVO.setIdentNo(identNo); //　证件号码
            certServiceRequestVO.setUserName(userName); // 用户名
            certServiceRequestVO.setIdentType(identType); // 证件类型
            certServiceRequestVO.setKeyAlg(raKeyAlg); // 秘钥算法
            certServiceRequestVO.setKeyLength(raKeyLength); // 秘钥长度
            certServiceRequestVO.setCertType(raCertType); // 证书类型
            certServiceRequestVO.setCustomerType(custType);// 客户类型
            //certServiceRequestVO.setBranchCode(raBranchCode); // 机构号
            //certServiceRequestVO.setDuration(duration);// 有效期
            certServiceRequestVO.setPersonnelCode(raPrincCode);//负责人编号
            certServiceRequestVO.setParentType(raParentType);// 客户类型
            certServiceRequestVO.setParentCode(raParentCode);// 机构号
            certServiceRequestVO.setP10 (p10Base64); // P10数据

            certServiceResponseVO = (CertServiceResponseVO)client.process(certServiceRequestVO);
        } catch (TKException e) {
            throw new PluginException("Create Cert CFCA Client return exception: " + e.getMessage());
        }

        printCertInfo(certServiceResponseVO);
        // RA 返回结果
        if (!BankUnionClient.SUCCESS.equals(certServiceResponseVO.getResultCode())) {
            throw new PluginException("ra return: " + certServiceResponseVO.getResultMessage());
        }

        // 申请成功，下载证书
//        try{
//            String serialNo = certServiceResponseVO.getSerialNo();
//            String authCode = certServiceResponseVO.getAuthCode();
//
//            CertServiceRequestVO certServiceRequestVO = new CertServiceRequestVO();
//            certServiceRequestVO.setTxCode(raDownload); // 接口URL
//            certServiceRequestVO.setAuthCode(authCode); // 证书编号
//            certServiceRequestVO.setSerialNo(serialNo); // 证书认证码
//            certServiceRequestVO.setP10(p10Base64); // P10数据
//
//            certServiceResponseVO = (CertServiceResponseVO) client.process(certServiceRequestVO);
//        }catch (TKException e){
//            throw new PluginException("Download Cert Exception : " + e.getMessage());
//        }
//
//        if(!BankUnionClient.SUCCESS.equals(certServiceResponseVO.getResultCode())){
//            throw new PluginException("Cert Download Exception :" + certServiceResponseVO.getResultMessage());
//        }

        String P10Cert = certServiceResponseVO.getSignatureCert();
        String dn = certServiceResponseVO.getDn();
        LOG.info("dn is:"+certServiceResponseVO.getDn());
        if (null == P10Cert || "".equals(P10Cert.trim())) {
            throw new PluginException("Sinnature cert is null from RA");
        }
        int index = 0;
        Connection conn = null;
        try {
            conn = this.uasServiceProvider.getUasConnection(true);
            if (index > 1) {
                updateCertDNIndex(identType, userName, identNo, index, conn);
            } else {
                insertCertDNIndex(identType, userName, identNo, index, conn);
            }
        } catch (Exception e) {
            LOG.error("Insert cert dn exception: " + e.getMessage());
        } finally {
            close(conn);
        }
        // 签名证书必须转为Base64 URL
        try {
            byte[] bytes = Convert.fromBase64(P10Cert);
            P10Cert = Convert.toBase64(bytes);
        } catch (Exception e) {
            throw new PluginException("Convert base64 url eceptin: " + e.getMessage());
        }
        // 返回响应数据
        CertBean certBean = new CertBean();
        certBean.setCertText(P10Cert);
        // certBean.setDn(dn);
        return certBean;
    }

    /**
     * 认证完成 验签
     */
    @Override
    public boolean verifySignature(P7Bean p7Bean) throws PluginException {

        if (null == p7Bean || p7Bean.getP7().length <= 0) {
            throw new PluginException("verify p7 data is null");
        }
        // 转为base64
        String p10Base64 = null;
        try {
            p10Base64 = toBase64String(p7Bean.getP7());
            LOG.info("p10Base is :" + p10Base64);
        } catch (Exception e) {
            throw new PluginException("Convert base64 eceptin: " + e.getMessage());
        }

        byte[] bytes = fromBase64(p10Base64);
        byte[] original;
        if(p7Bean.getAlgorithm() == 7){
            original = SM2Utils.sm2original(bytes);
        }else{
            original = SM2Utils.rsaoriginal(bytes);
        }

        String url = allConfig.get(SVS_URL + point + p7Bean.getAppID());
        if (null == url || url.isEmpty()) {
            throw new PluginException("Please add svs.url on the fido admin");
        }
        LOG.info("get svs.url is :" + url);

        String port = allConfig.get(SVS_PORT + point + p7Bean.getAppID());
        if (null == port || port.isEmpty()) {
            throw new PluginException("Please add svs.port on the fido admin");
        }
        int portStr = Integer.parseInt(port);
        LOG.info("get svs.port is :" + portStr);

        String timeout = allConfig.get(SVS_TIMEOUT + point + p7Bean.getAppID());
        if (null == timeout || timeout.isEmpty()) {
            throw new PluginException("Please add ra.timeout on the fido admin");
        }
        int timeoutStr = Integer.parseInt(timeout);
        LOG.info("get svs.timeout is :" + timeoutStr);

        try{
            Svs2ClientHelper helper = Svs2ClientHelper.getInstance();
            helper.init(url,portStr,timeoutStr);

            Svs2ClientHelper.SvsResultData srd = helper.pkcs7Verify(p10Base64,original);
            LOG.info("=======================================");
            LOG.info("=======================================");
            if(srd.m_errno == 0) {
                return true;
            }
        }catch (Exception e){
            throw new PluginException("verify Signature Exception :" + e.getMessage());
        }
        return false;
    }

    /**
     * 注销单个、多个 注销证书
     */
    @Override
    public byte[] revokeCert(CertBean certBean,String appId) throws PluginException {

        LOG.debug ("=============注销程序启动===============");
        // 参数校验
        if (certBean == null || certBean.getCertText().length() <= 0) {
            throw new PluginException("revoke cert data is null");
        }
        LOG.debug ("============注销程序启动成功=============");
        // 获取DN
        String dn=null;
        String certIdentiValue = null;
        try {
            byte[] encodedCert = Convert.fromBase64(certBean.getCertText());
            LOG.debug (encodedCert);

            if(certBean.getAlgorithm () == 7){
                org.bouncycastle.asn1.x509.Certificate cert = null;
                cert = SM2Utils.getCert (encodedCert);
                ASN1Integer asn1Integer = cert.getTBSCertificate ().getSerialNumber ();
                LOG.debug ("ans1Integer is : " + asn1Integer );
                certIdentiValue = asn1Integer.toString ();
                LOG.debug ("certIdentiValue is : " + certIdentiValue);

                X500Name x500Name = cert.getTBSCertificate ().getSubject ();
                String dnJson = x500Name.toString ();
                dn = parsing (dnJson);
                LOG.debug ("cert dn is :" + dn);
            }else{
                CertificateFactory cf = CertificateFactory.getInstance ("X.509");
                LOG.debug ("cf is " + cf);
                if((encodedCert != null) && (encodedCert.length > 0)){
                    X509Certificate cert = (X509Certificate)cf.generateCertificate (new ByteArrayInputStream (encodedCert));
                    // 证书主体信息
                    dn = cert.getSubjectDN ().getName ().replaceAll (", ",",");
                    LOG.debug ("cert dn is :" + dn);
                }
            }
        } catch (Exception e) {
            throw new PluginException("Failed to get dn: " + e.getMessage());
        }

        // 注销接口名称
        String raDereg = getConfigFromFidoAdmin(RA_DEREG+point+appId, "Please add ra.dereg on the fido admin");
        // 加载CFCA Client
        BankUnionClient client = getRaClint(appId);
        if (client == null) {
            throw new PluginException("Failed to load ra config of revokeCert method");
        }
        CertServiceResponseVO certServiceResponseVO;
        try {
            CertServiceRequestVO certServiceRequestVO = new CertServiceRequestVO();
            certServiceRequestVO.setDn(dn);
            certServiceRequestVO.setTxCode(raDereg);
            certServiceResponseVO = (CertServiceResponseVO) client.process(certServiceRequestVO);
            String retCode = certServiceResponseVO.getResultCode();
            LOG.debug("=============== 注销状态码 =============== " + retCode);
            if (!BankUnionClient.SUCCESS.equals(certServiceResponseVO.getResultCode())) {
                throw new PluginException("ra return: " + certServiceResponseVO.getResultMessage());
            }
        } catch (Exception e) {
            throw new PluginException("RevokeCert CFAC RA Client is exception: " + e.getMessage());
        }
        LOG.debug("=============== 注销状态码 =============== " + certServiceResponseVO.getResultCode());
        LOG.debug("=============== 注销结果信息 ============= " + certServiceResponseVO.getResultMessage());
        return null;
    }

    /**
     * 重新排列证书DN顺序算法
     */
    public static String parsing(String dn){

        String[] dns = dn.split (",");
        String[] dnStr = new String[5];
        String dnResult = "";

        for(String rdn : dns){
            String[] rdns = rdn.split ("=");
            if(rdns[0].trim ().equals ("OU")){
                if(rdns[1].length () <= 5){
                    dnStr[2] = rdn.trim ();
                }else{
                    dnStr[1] = rdn.trim ();
                }
            }else if(rdns[0].trim ().equals ("C")){
                dnStr[4] = rdn.trim ();
            }else if(rdns[0].trim ().equals ("O")){
                dnStr[3] = rdn.trim ();
            }else if(rdns[0].trim ().equals ("CN")){
                dnStr[0] = rdn.trim ();
            }
        }
        for(int i = 0;i < dnStr.length;i ++){
            dnResult = dnResult + dnStr[i] +",";
        }
        dnResult = dnResult.substring (0,dnResult.length () -1);
        return dnResult.trim ();
    }

    public void updateCertDNIndex(String cardType, String cardName, String cardNO, int dnIndex, Connection conn) throws PluginException {

        PreparedStatement s = null;
        ResultSet rs = null;
        String sql = "UPDATE t_certificate_dn set dn_index = ? where card_type = ? and card_no = ? and card_name = ? ";

        try {
            int offset = 1;
            s = conn.prepareStatement(sql);
            s.setInt(offset++, dnIndex);
            s.setString(offset++, cardType);
            s.setString(offset++, cardNO);
            s.setString(offset++, cardName);
            s.executeUpdate();
        } catch (SQLException sqle) {
            LOG.error("The following SQL statement failed to execute:\n {}",
                    sql);
            LOG.error("The following SQL statement failed to execute " + sql, sqle);
            throw new PluginException("Failed to update certificate info to database");
        } finally {
            close(rs);
            close(s);
        }
    }

    public void insertCertDNIndex(String cardType, String cardName, String cardNO, int dnIndex, Connection conn) throws PluginException {

        PreparedStatement s = null;
        ResultSet rs = null;
        String sql = "INSERT INTO t_certificate_dn (t_cert_dn_id,dn_index,card_type,card_no,card_name) VALUES (?,?,?,?,?)";

        try {
            int offset = 1;
            s = conn.prepareStatement(sql);
            s.setString(offset++, Convert.generateID());
            s.setInt(offset++, dnIndex);
            s.setString(offset++, cardType);
            s.setString(offset++, cardNO);
            s.setString(offset++, cardName);
            s.executeUpdate();
        } catch (SQLException sqle) {
            LOG.error("The following SQL statement failed to execute:\n {}",
                    sql);
            LOG.error("The following SQL statement failed to execute " + sql, sqle);
            throw new PluginException("Failed to update certificate info to database");
        } finally {
            close(rs);
            close(s);
        }
    }

    /**
     * CFCA RA Client
     */
    public BankUnionClient getRaClint(String appId) throws PluginException {

        try {
            // 服务器地址
            LOG.info("get ra.url from redis:"+RA_URL+point+appId);
            String url = allConfig.get(RA_URL+point+appId);
            if (null == url || url.isEmpty()) {
                throw new PluginException("Please add ra.url on the fido admin");
            }
            LOG.info("get ra.url is :" + url);

            // 连接超时时间
            LOG.info("get ra.timeout is :" + RA_TIMEOUT + point  + appId);
            String timeoutStr = allConfig.get(RA_TIMEOUT+point+appId);
            if (null == timeoutStr || timeoutStr.isEmpty()) {
                throw new PluginException("Please add ra.timeout on the fido admin");
            }
            int timeout = Integer.parseInt(timeoutStr);
            LOG.info("get ra.timeout is :" + timeout)
            ;
            // 读取超时时间
            LOG.info("get ra.readTimeout is :" + RA_READ_TIMEOUT + point + appId);
            String readTimeoutStr = allConfig.get(RA_READ_TIMEOUT + point + appId);
            if(readTimeoutStr == null || readTimeoutStr.isEmpty()){
                throw new PluginException("Please add ra.readTime on the Fido Admin");
            }
            int readTimeout = Integer.parseInt(readTimeoutStr);
            LOG.info("get ra.readTimeout is :" + readTimeout);

            // 通信证书配置
            LOG.info("get keyStorePath is :" + CONTENT_CERT_CONFIG + point + appId);
            String keyStorePath = allConfig.get(CONTENT_CERT_CONFIG + point + appId);
            LOG.info("get keyStorePath is :" + keyStorePath);

            LOG.info("get keyStorePassword is :" + CONTENT_CERT_PASSWORD + point + appId);
            String keyStorePassword = allConfig.get(CONTENT_CERT_PASSWORD + point + appId);
            LOG.info("get keyStorePassword is :" + keyStorePassword);

            String trustStorePath = allConfig.get(TRUST_STORE_PATH + point + appId);
            LOG.info("get trustStorePath is:" + trustStorePath);

            String trustStorePassword = allConfig.get(TRUST_STORE_PASSWORD + point + appId);
            LOG.info("get trustStorePassword is :" + trustStorePassword);

            LOG.info("===================开始连接RA服务=====================");
            BankUnionClient client = new BankUnionClient(url,timeout,readTimeout);
            LOG.info("====================================================");
            client.initSSL(keyStorePath,keyStorePassword,trustStorePath,trustStorePassword);
            LOG.info("===================连接RA服务成功=====================");

            return client;
        } catch (Exception e) {
            throw new PluginException("Failed to load ra client exception: " + e.getMessage());
        }
    }

    /**
     * 直接从管理系统加载配置信息
     */
    private String getConfigFromFidoAdmin(String str, String errorInfo) throws PluginException {

        if (null == allConfig || allConfig.isEmpty()) {
            throw new PluginException("AllConfig is null of getConfigFromFidoAdmin method");
        }
        String name = allConfig.get(str);
        if (null == name || name.isEmpty()) {
            throw new PluginException(errorInfo);
        }
        return name;
    }

    /**
     * 优先用户上送，否则从管理系统加载配置信息
     */
    private String getConfigFromUser(String param, String str, String errorInfo) throws PluginException {
        if (null == allConfig || allConfig.isEmpty()) {
            throw new PluginException("AllConfig is null of getConfigFromUser method");
        }
        if (null == param || param.isEmpty()) {
            param = allConfig.get(str);
            if (null == param || param.isEmpty()) {
                throw new PluginException(errorInfo);
            }
        }
        return param;
    }

    // 输出 RA 返回信息
    private void printCertInfo(CertServiceResponseVO certServiceResponseVO) {

        LOG.debug("=============== 注册结果 =============== " + certServiceResponseVO.getResultCode());
        LOG.debug("getResultMessage: " + certServiceResponseVO.getResultMessage());
        if (BankUnionClient.SUCCESS.equals(certServiceResponseVO.getResultCode())) {
            LOG.debug("getDn: " + certServiceResponseVO.getDn());
            LOG.debug("getSequenceNo: " + certServiceResponseVO.getSequenceNo());
            LOG.debug("getSerialNo: " + certServiceResponseVO.getSerialNo());
            LOG.debug("getStartTime: " + certServiceResponseVO.getStartTime());
            LOG.debug("getEndTime: " + certServiceResponseVO.getEndTime());
            LOG.debug("getSignatureCert: " + certServiceResponseVO.getSignatureCert());
            LOG.debug("getEncryptionCert: " + certServiceResponseVO.getEncryptionCert());
            LOG.debug("getEncryptionPrivateKey: " + certServiceResponseVO.getEncryptionPrivateKey());
            LOG.debug("getSignatureCertSub: " + certServiceResponseVO.getSignatureCertSub());
            LOG.debug("getEncryptionCertSub: " + certServiceResponseVO.getEncryptionCertSub());
            LOG.debug("getEncryptionPrivateKeySub: " + certServiceResponseVO.getEncryptionPrivateKeySub());
        }
    }

    @Override
    public Map<String, String> getDN(String dn) throws PluginException {

        JsonObject jsonObject = new JsonParser().parse(dn).getAsJsonObject();
        JsonElement cardNOElement = jsonObject.get("cardNO");
        JsonElement cardTypeElement = jsonObject.get("cardType");
        JsonElement cardNameElement = jsonObject.get("cardName");
        String cardNO = cardNOElement.getAsString();
        String cardType = cardTypeElement.getAsString();
        String cardName = cardNameElement.getAsString();

        Connection conn = null;
        PreparedStatement s = null;
        ResultSet rs = null;
        try {
            int dnIndex = 0;
            conn = this.uasServiceProvider.getUasConnection(true);
            String sql = "SELECT dn_index from t_certificate_dn  where card_type = ? and card_no = ? and card_name = ? ";
            s = conn.prepareStatement(sql);
            s.setString(1, cardType);
            s.setString(2, cardNO);
            s.setString(3, cardName);
            rs = s.executeQuery();
            while (rs.next()) {
                dnIndex = rs.getInt("dn_index");
            }
            dnIndex++;
            jsonObject.addProperty("dnIndex", dnIndex);
            String result = "CN=041@N" + cardNO + "@" + cardName + "@" + dnIndex + ",OU=Organizational-1,OU=LZBANKPHONESHIELDFD,O=TEST OCA31,C=CN";
            Map<String, String> resultMap = new HashMap<String, String>();
            resultMap.put("certDN", result);
            resultMap.put("certDNJson", jsonObject.toString());
            return resultMap;

        } catch (SQLException sqle) {
            LOG.error("Failed to  connect to database, ", sqle);
            throw new PluginException("Failed to connect to database");
        } catch (Exception e) {
            e.printStackTrace();
            LOG.error(e);
            throw new PluginException("Filed to getDN");
        } finally {
            close(s);
            close(rs);
            close(conn);
        }
    }

    /**
     * 电子签章功能
     * @param transactionText
     * @return
     * @throws PluginException
     */
    @Override
    public CertTransactionTextBean getCertTransactionText(String transactionText) throws PluginException {

        CertTransactionTextBean certTransactionTextBean = new CertTransactionTextBean();
        JsonObject jsonObject = new JsonParser().parse(transactionText).getAsJsonObject();
        JsonElement showFlagElement = jsonObject.get("showFlag");
        JsonElement showTextElement = jsonObject.get("showText");
        JsonElement esFlagElement = jsonObject.get("esFlag");
        JsonElement esHashElement = jsonObject.get("esHash");
        if (null != showFlagElement) {
            certTransactionTextBean.setShowFlag(showFlagElement.getAsString());
        } else {
            certTransactionTextBean.setShowFlag("00");
        }
        String text = "";
        if (null != showTextElement) {
            if (null != showTextElement) {
                text = showTextElement.getAsString();
            }
        }
        certTransactionTextBean.setShowText(text);
        if (null != esFlagElement) {
            certTransactionTextBean.setEsFlag(esFlagElement.getAsString());
        }
        if (null != esHashElement) {
            certTransactionTextBean.setEsHash(esHashElement.getAsString());
        }
        return certTransactionTextBean;
    }

    public static void main(String[] args) throws Exception {

        String a = "MIIEaTCCA1GgAwIBAgIFQCQRl4IwDQYJKoZIhvcNAQELBQAwXTELMAkGA1UEBhMCQ04xMDAuBgNVBAoMJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEcMBoGA1UEAwwTQ0ZDQSBBQ1MgVEVTVCBPQ0EzMTAeFw0yMDA2MDUwNzAwNDlaFw0yMDA2MTcwNzAwNDlaMIGQMQswCQYDVQQGEwJjbjETMBEGA1UECgwKVEVTVCBPQ0EzMTEcMBoGA1UECwwTTFpCQU5LUEhPTkVTSElFTERGRDEZMBcGA1UECwwQT3JnYW5pemF0aW9uYWwtMTEzMDEGA1UEAwwqMDQxQE4zMTAxMTQxOTkzMTEyNzI2NDJA5pyx5b+D5oChQDAwMDAwMDA2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1SpS6Uyv4JJ5lo6ix3rBH71dp8mEiMQMCu8ziHeW9+fR1BcDJtvbWBm6aVBkMwZKxnB9ldFDNssg+G/vVuKWELqsubkXOCbNhOkc9E54X8n69F75eCEh+IJ8ZhujPEt31CWdwndde+bDyFL32B06Vy+0ImzfLeueOKQq8Sz5y70IJRyiYc8U65sIG6A8pPII9J1wMUZtkpmH4Vw2dAqB1nmYsXsN5oqwbr3q/iA+UPqB4i37xqdlv1Ymapq/siLv+SPjHj6+nb9upK++Gj70HkBwlktfxey5kiibA9i+UBHdX9YjSG++1csosUzo/TeaNOJzK4JR9F57UI9F4QNUwQIDAQABo4H7MIH4MD8GCCsGAQUFBwEBBDMwMTAvBggrBgEFBQcwAYYjaHR0cDovL29jc3B0ZXN0LmNmY2EuY29tLmNuOjgwL29jc3AwHwYDVR0jBBgwFoAUmj20rmVY+85aBXgmoG0rBIa6xuwwDAYDVR0TAQH/BAIwADA4BgNVHR8EMTAvMC2gK6AphidodHRwOi8vMjEwLjc0LjQyLjMvT0NBMzEvUlNBL2NybDIwNS5jcmwwDgYDVR0PAQH/BAQDAgbAMB0GA1UdDgQWBBQZx2BS/88hHaziiwD31ZvIX6ufDzAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwDQYJKoZIhvcNAQELBQADggEBAEokP92udTzKekdxPnC6YiSop9Hu9uPGSG4e7ZFaMJWHeq4acock3fJO6tS4I2zPqQbiaQZpPCHfRdOOJDDHg5y5Gy4ses8g6osj6orqkVaHzTobp49tOYXRGY2awif1Raw0zdk4QFVRD6pL4+X8G/n4UG60QNUswH2vjZUBLy6P8lxk3/WVz9U4+ByzURlfI8N2m5Caau7atje1+8wWDQrDdyIJfaNtotNffOsf/UH659h399S6Ou7+Sc50+3Lg0HEj7h6ARkPVj8/7Ptb+MirKWQpRUcrHknWBylEojiJDEahJOoDH+zjQQIQeI5k3/eeUE9iAn2VHohovA/JHnVo=";
        String dn;
        try {
            byte[] encodedCert = Convert.fromBase64(a);
            // 解析证书
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(encodedCert));
            // 证书主体信息
            dn = cert.getSubjectDN().getName().replaceAll(" ", "");
            LOG.debug("cert dn is:"+dn);
        } catch (Exception e) {
            throw new PluginException("Failed to get dn: " + e.getMessage());
        }
    }

}